package com.paradogs.gs.modules.world.entity;

import com.paradogs.common.utils.SpringUtils;
import com.paradogs.gs.db.WorldNodeDB;
import com.paradogs.gs.misc._NetMgr;
import com.paradogs.gs.modules.WorldObject;
import com.paradogs.gs.modules.WorldSyncData;
import com.paradogs.gs.modules.world.base.WorldNodeProto;
import com.paradogs.gs.modules.world.WorldService;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author: yumi
 * @date: 2025/3/31  16:21
 * @Description: 世界节点
 */
@Data
@NoArgsConstructor
public class WorldNode {

    // ID
    private Long id;
    // 所属场景 ID
    private Integer sceneId;
    // X 坐标
    private Integer x;
    // Y 坐标
    private Integer y;
    // 节点名称
    private String name;
    // 描述
    private String description;
    // 是否可以 pk
    private Boolean pk;

    // 存在的单位
    private Map<Long, WorldObject> objectMap = new LinkedHashMap<>();
    // 周围节点
    private WorldNode north;    // 北
    private WorldNode east;     // 东
    private WorldNode south;    // 南
    private WorldNode west;     // 西

    public WorldNode(WorldNodeDB db) {
        this.id = db.getId();
        this.sceneId = db.getSceneId();
        this.x = db.getX();
        this.y = db.getY();
        this.name = db.getName();
        this.description = db.getDescription();
        this.pk = db.getPk();
    }

    public String key() {
        return key(x, y);
    }

    public static String key(int x, int y) {
        return x + "," + y;
    }

    /** 加载周围节点 */
    public void link(Map<String, WorldNode> cache) {
        this.north  = cache.get(key(x, y + 1));
        this.east   = cache.get(key(x + 1, y));
        this.south  = cache.get(key(x, y - 1));
        this.west   = cache.get(key(x - 1, y));
    }

    /** 获得所属世界 */
    public BigWorld world() {
        return SpringUtils.getBean(WorldService.class).getBigWorld(sceneId);
    }

    @Override
    public String toString() {
        return String.format("%s(%s,%s)", name, x, y);
    }

    public void leave(WorldObject object) {
        if (!objectMap.containsKey(object.getId())) {
            return;
        }
        objectMap.remove(object.getId());
        for (WorldObject other : objectMap.values()) {
            if (other != object && other.isPlayer() && other.getPlayer().isNet()) {
                other.getPlayer()._netMgr().worldNodeLeave(object.toSyncData());
            }
        }
    }

    public void enter(WorldObject object) {
        object.setX(this.x);
        object.setY(this.y);
        objectMap.put(object.getId(), object);
        for (WorldObject other : objectMap.values()) {
            if (other != object && other.isPlayer() && other.getPlayer().isNet()) {
                other.getPlayer()._netMgr().worldNodeEnter(object.toSyncData());
            }
        }
        if (object.isPlayer() && object.getPlayer().isNet()) {
            object.getPlayer()._netMgr().worldNodeInfo(new WorldNodeProto(this));
        }
    }

    public void updateObject(WorldSyncData syncData) {
        for (WorldObject other : objectMap.values()) {
            if (other.isPlayer() && other.getPlayer().isNet()) {
                other.getPlayer()._netMgr().worldNodeUpdateObject(syncData);
            }
        }
    }

    public WorldObject findObject(Long id) {
        return objectMap.get(id);
    }

}
